﻿using System;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using System.Xml.Linq;
using DotNetOpenAuth.OAuth;
using NHibernate;
using Web.Extensions;
using Web.HelperClasses;
using Web.HelperClasses.AvatarService;
using Web.Model;
using Web.OAuth;

namespace Web.Controllers
{
    public class GoogleLoginController : OAuthLoginController
    {
		protected override string TokenManagerKey
		{
			get { return "GoogleTokenManager"; }
		}
		protected override string CustomerKey
		{
			get { return "googleConsumerKey"; }
		}
		protected override string CustomerSecret
		{
			get { return "googleConsumerSecret"; }
		}
		
		private string GoogleAccessToken
        {
            get { return (string)Session["GoogleAccessToken"]; }
            set { Session["GoogleAccessToken"] = value; }
        }

        [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Head)]
        public override ActionResult SendRequest(Uri callbackUri)
        {
            var tokenManager = GetTokenManager();
            if (tokenManager != null)
            {
                var google = new WebConsumer(GoogleConsumer.ServiceDescription, tokenManager);

                // If we don't yet have access, immediately request it.
                GoogleConsumer.Applications scope = GoogleConsumer.Applications.Contacts;
                GoogleConsumer.RequestAuthorization(google, scope, Url.ActionAbsolute("Callback", new { callbackUri }));
            }
            return null;
        }

        [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Head)]
        public override ActionResult Callback(Uri callbackUri)
        {
            var tokenManager = GetTokenManager();
            if (tokenManager != null)
            {
                var google = new WebConsumer(GoogleConsumer.ServiceDescription, tokenManager);

                // Is Google calling back with authorization?
                var accessTokenResponse = google.ProcessUserAuthorization();
                if (accessTokenResponse != null)
                {
                    this.GoogleAccessToken = accessTokenResponse.AccessToken;
                }

                if (this.GoogleAccessToken != null)
                {
                    var accountInfo = new GoogleAccountInfo(tokenManager, this.GoogleAccessToken);
                    CreateOrAuthorizeUser(accountInfo);
                }
                else
                {
                    throw new InvalidDataException("GoogleAccessToken is missing");
                }
            }
            return Redirect(callbackUri.AbsoluteUri);
        }

        public GoogleLoginController(ISession session, IUserSession userSession, AvatarService avatarService)
            : base(session, userSession, avatarService)
        {
        }
    }

    internal class GoogleAccountInfo : AccountInfo
    {
        private WebConsumer consumer;
        private string accessToken;

        public GoogleAccountInfo(InMemoryTokenManager tokenManager, string accessToken)
        {
            consumer = new WebConsumer(GoogleConsumer.ServiceDescription, tokenManager);
            this.accessToken = accessToken;
            XDocument contactsDocument = GoogleConsumer.GetContacts(consumer, accessToken, 1, 1);
            XNamespace defaultNamespace = contactsDocument.Root.GetDefaultNamespace();
            var authorElement = contactsDocument.Root.Elements(defaultNamespace + "author").First();
            Email = authorElement.Element(defaultNamespace + "email").Value;
            Name = authorElement.Element(defaultNamespace + "name").Value;
            AccountSource = AccountSource.Gmail;
        }

        public override Stream GetAvatarInputStream()
        {
            return null;//GoogleConsumer.GetProfileImage(consumer, accessToken, Email);
        }

    }
}
